import dayjs from 'dayjs'
import { clearStorage } from './localstoreage'
import { message } from '@/libs/global/antDesignVue'
import deepClone from './deepClone'
import { clearSession } from './sessionStorage'

/**
 * 登出
 */
export function logout() {
  clearStorage()
  clearSession()
  location.reload()
}

/**检测数据类型 */
export function checkDataType(val: any) {
  if (Array.isArray(val)) {
    return 'array'
  } else if (val instanceof Object) {
    return 'object'
  } else if (typeof val === 'string') {
    return 'string'
  } else if (typeof val === 'number') {
    return 'number'
  } else if (val === null) {
    return null
  } else if (val === undefined) {
    return undefined
  } else {
    return val
  }
}

/**复杂数据递归查询所有属性 */
export function checkComplexDataw(
  data: any,
  cb?: (loopData: any, keyList: (string | number)[]) => boolean
) {
  if (typeof data === 'string') return
  // 控制跳出闭包
  let flag = false

  // 对象/数组 的 key值列表/下标列表
  let keyList: (string | number)[] = []

  loop(data)

  function loop(loopData: any) {
    if (flag) return
    if (checkDataType(loopData) === 'array') {
      const copyData = loopData.flat(Infinity)
      const currentIdx = keyList.length
      for (let i = 0; i < copyData.length; i++) {
        if (keyList.length > currentIdx) {
          keyList = keyList.slice(0, currentIdx)
          keyList[currentIdx] = i
        } else {
          keyList.push(i)
        }
        loop(copyData[i])
      }
      keyList.splice(keyList.length - 1, 1)
    } else if (checkDataType(loopData) === 'object') {
      for (const key in loopData) {
        keyList.push(key)
        loop(loopData[key])
      }
      keyList.splice(keyList.length - 1, 1)
    } else if (cb && typeof cb === 'function') {
      const returnData = cb(loopData, keyList)
      keyList.splice(keyList.length - 1, 1)
      flag = returnData === false
    }
  }
}

/**简单数据数据非空校验，或者复杂数据内是否包含null或者undefined */
export function checkEmpty(data: any) {
  let flag = false
  checkComplexDataw(data, (loopData: any) => {
    if ((loopData ?? null) === null || isNaN(loopData)) {
      flag = true
      return false
    } else {
      return true
    }
  })
  return flag
}

/**树形结构数据递归查询所有子项 */
export function treeMap(target: any, childrenKey: any, cb?: Function): any {
  if (Array.isArray(target)) {
    for (let i = 0; i < target.length; i++) {
      const data = target[i]
      if (typeof cb === 'function') {
        const bol = cb(data)
        if (bol) return true
      }
      // treeMap继续检查当前项
      const bol = treeMap(data, childrenKey, cb)
      if (bol) return true
    }
  } else if (target instanceof Object) {
    // 存在子项时
    if (Array.isArray(target[childrenKey]) && target[childrenKey].length) {
      const bol = treeMap(target[childrenKey], childrenKey, cb)
      if (bol) return true
    }
  }
}

/**去除多余回车,制表符(tab),空格 */
export function removeStrInvaildSymb(data: string) {
  return checkDataType(data) === 'string' ? data.trim().replace(/\S|\n|\t/g, '') : data
}

/**判断是否是URL字符串 */
export function IsURL(strUrl: string): boolean {
  const v = new RegExp(
    '^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$',
    'i'
  )
  return v.test(strUrl)
}

/**根据文件流下载文件 */
export function downFile(blobOfFile: Blob, option: { fileName?: string; type?: string }) {
  let { fileName } = option

  const aLink = document.createElement('a')
  // // 这里是将url转成blob地址，
  // let res = await fetch(link, { mode: 'no-cors' })
  // console.log(res)
  // let blob = await(res as Response).blob()
  // console.log(blob)
  // if (!blob.type)
  //   return notification.error({
  //     message: '提示',
  //     description: '文件下载失败',
  //   })
  // let blobAB = await blobOfFile.arrayBuffer()
  // let blob = new Blob(blobAB, { type: blobOfFile.type })
  // 将链接地址字符内容转变成blob地址

  if (blobOfFile.size === 0) return message.error('暂无数据可下载')
  const nowTiem = dayjs().format('YYYY-MM-DD-HH-mm-ss')
  let filename = ''
  if (fileName) filename = fileName + '_' + nowTiem
  if ('download' in document.createElement('a')) {
    aLink.style.display = 'none'
    aLink.href = URL.createObjectURL(blobOfFile)
    aLink.download = filename || nowTiem //下载的文件的名字
    document.body.appendChild(aLink)
    aLink.click()
    document.body.removeChild(aLink)
  } else {
    // IE10+下载
    // window.navigator.msSaveBlob(blob, fileName)
    alert('请使用IE浏览器以外的浏览器进行下载！')
  }
}

/**下拉选择输入关键字筛选 */
export const filterOption = (input: string, option: any, target?: string) => {
  return option[target || 'label'].toLowerCase().indexOf(input.toLowerCase()) >= 0
}

/**判断元素滚动到父元素底部 */
export const domIsScrollBottom = (parentId: string): boolean => {
  const scrollHeight = document.getElementById(parentId)?.scrollHeight as number
  const offsetHeight = document.getElementById(parentId)?.offsetHeight as number
  const scrollTop = document.getElementById(parentId)?.scrollTop as number
  const diffHeight = scrollHeight - (offsetHeight + scrollTop)
  if (diffHeight <= 10) {
    return true
  } else {
    return false
  }
}

/**
 *
 * @param px 像素值
 * @returns px转为rem
 */
export const px2rem = (px: number) => {
  const rootFontSize = getComputedStyle(document.documentElement).fontSize.split('px')[0]
  return px / Number(rootFontSize)
}

/**
 * 设置网页根字体大小
 * @param fontSize 字体大小
 */
export const setWindowRootFontSize = (fontSize?: number) => {
  const currentWidth = getComputedStyle(document.documentElement).width.split('px')[0]
  const scale = Number(currentWidth) / 1920
  document.documentElement.style.fontSize = scale * 16 + 'px'
}

/**
 * echart图表tooltip自定义html
 *
 * @desc series中的data为多维数组时，请将value放在最后一维中，此处判断series.data为数组时，取的最后一维当value展示
 */
export function coustomEchartTooltip(
  params: any,
  data?: {
    contentTitle?: string
    contentLeftText?: string
    contentValueUnit?: string
    contentLeftTextKey?: string
  }
) {
  const { contentLeftText, contentLeftTextKey, contentTitle, contentValueUnit } = Object.assign(
    {},
    data
  )

  const tooltip = document.createElement('div')
  tooltip.className = 'tooltip'

  const blurMask = document.createElement('div')
  blurMask.className = 'tooltip-blurMask'
  tooltip.appendChild(blurMask)

  const title = document.createElement('p')
  title.className = 'noHanzi tooltip-title'
  title.innerText =
    (contentTitle ?? null) === null ? params.map((param: any) => param.name) : contentTitle

  tooltip.appendChild(title)

  if (Array.isArray(params)) {
    for (let i = 0; i < params.length; i++) {
      const param = params[i]

      const name = contentLeftTextKey ? param[contentLeftTextKey] : param.name

      const value =
        (Array.isArray(param.value) ? Math.abs(param.value.slice(-1)[0]) : Math.abs(param.value)) +
        (contentValueUnit || '')

      const content = document.createElement('div')
      content.className = 'tooltip-content'

      const contentLeft = document.createElement('span')
      contentLeft.className = 'hanzi contentLeft'

      contentLeft.innerText = param.data.toolTipConentLeftText || contentLeftText || name

      const contentRight = document.createElement('span')
      contentRight.className = 'noHanzi contentRight'
      contentRight.innerText = value

      content.appendChild(contentLeft)
      content.appendChild(contentRight)

      i !== params.length - 1 && (content.style.marginBottom = '8px')
      tooltip.appendChild(content)
    }
  } else {
    const name = params.name
    const value = params.value + (contentValueUnit || '')

    const content = document.createElement('div')
    content.className = 'tooltip-content'

    const contentLeft = document.createElement('span')
    contentLeft.className = 'hanzi contentLeft'
    contentLeft.innerText = contentLeftText || name

    const contentRight = document.createElement('span')
    contentRight.className = 'noHanzi contentRight'
    contentRight.innerText = value

    content.appendChild(contentLeft)
    content.appendChild(contentRight)

    tooltip.appendChild(content)
  }
  return tooltip
}

/**
 *
 * @param str
 * @returns 判断并返回str是否是空，N/A也是空的一种
 */
export function checkDataIsNull(str: string) {
  return str && str !== 'N--'
}

/**
 *
 * @param  data 省市区
 * @returns 返回组合后的省市区
 */
export function addressJoin({
  province,
  city,
  district
}: {
  province: string
  city: string
  district: string
}) {
  const address: string[] = []
  if (checkEmpty(province)) {
    address.push(province)
  }

  if (checkEmpty(city)) {
    address.push(city)
  }

  if (checkEmpty(district)) {
    address.push(district)
  }
  return address.length ? address.join('-') : '暂未设置地址'
}

export function long2Chinese(data: number) {
  let dataClone = data
  const unit = ['', '万', '亿']
  const decimal = ['', '十', '百', '千']
  let str = ''
  let curNum = 0
  let unitIndex = 0

  while (dataClone > 0) {
    curNum = dataClone % 10000
    if (curNum !== 0) {
      str = toChinese(curNum) + unit[unitIndex] + str
    }
    dataClone = Math.floor(dataClone / 10000)
    unitIndex++
  }

  function toChinese(num: number) {
    let str1 = ''
    let num1 = num
    let decimalIndex = 0
    while (num1 > 0) {
      const curNum1 = num1 % 10
      if (curNum1 !== 0) {
        str1 = decimal[decimalIndex] + numToChinese(curNum1) + str1
      }
      num1 = Math.floor(num1 / 10)
      decimalIndex++
    }
    return str1
  }

  function numToChinese(num: number) {
    switch (num) {
      case 0:
        return '零'
      case 1:
        return '一'
      case 2:
        return '二'
      case 3:
        return '三'
      case 4:
        return '四'
      case 5:
        return '五'
      case 6:
        return '六'
      case 7:
        return '七'
      case 8:
        return '八'
      case 9:
        return '九'
      default:
        return ''
    }
  }

  return str
}

/**
 * 将长数字转为带数量单位的简略数字
 * @param num 需要简略的数字
 */
export function long2Brief(num: number) {
  if (num === undefined) return { num: 0, unit: '' }
  let numStr = String(num)
  let isInt = true
  let index = 0
  while (numStr.length > 4) {
    if (Number(numStr.slice(-4)) > 0 && isInt) isInt = false
    numStr = numStr.slice(0, -4)
    index++
  }
  const obj = { num: Number(numStr), unit: '' }
  switch (index) {
    case 0:
      break
    case 1:
      obj.unit = isInt ? '万' : '余万'
      break
    case 2:
      obj.unit = isInt ? '亿' : '余亿'
      break
    case 3:
      obj.unit = isInt ? '万亿' : '余万亿'
      break
    case 4:
      obj.unit = isInt ? '兆' : '余兆'
      break
    case 5:
      obj.unit = isInt ? '京' : '余京'
      break
    default:
      break
  }
  return obj
}

/**
 * 字符转数字
 *
 * 会从字符中提取数字返回
 *
 * 如果字符中不包含数字，返回0
 *  */
export function str2num(val: string): number | undefined {
  const value = parseFloat((deepClone(val) as string).replace(/[^0-9|.|-]{0,}/g, ''))
  return isNaN(value) ? undefined : value
}

/**数字四舍五入 */
export function numRound(val: number, zeroNum = 1) {
  return Math.round(val * Math.pow(10, zeroNum)) / Math.pow(10, zeroNum)
}

/**
 *
 * @param val 传入的需要保留位数的字符或者数字
 * @param zeroNum 保留位数
 * @param overOmit 在补零阶段只补一个零，即时最终小数位并不会达到zeroNum的长度
 * @returns 补零完成后的字符
 */
export function zeroize(val: string | number, zeroNum = 1, overOmit = false): string {
  let value: number | undefined = undefined

  if (typeof val === 'string') {
    value = str2num(val)
  } else {
    value = val
  }

  if (value !== 0 && !value) return ''

  const returnData = numRound(value, zeroNum)

  const numStr = String(returnData)

  const numStrArr = numStr.split('.') || []

  const intArr = (numStrArr[0] || '').split('')

  const decimalsArr = (numStrArr[1] || '').split('')

  const decimalsLen = decimalsArr.length

  if (decimalsLen === zeroNum) {
    return String(returnData)
  } else {
    // 补零操作
    const decimalsStr = decimalsArr.join('').padEnd(overOmit ? 1 : zeroNum - decimalsLen, '0')

    const intStr = intArr.join('')

    return intStr + '.' + decimalsStr
  }
}

/**
 * 文本换行符替换
 * 将输入的文本中的换行符,替换成/n字符
 *
 */
export function replaceBreak(str: string) {
  return str.replace(/(\n)+/g, '\\' + 'n')
}

export function unReplaceBreak(str: string) {
  return str.replace(/\\n/g, '\n')
}
